/*
 * Bitmap.java
 *
 * Created on 2006年1月3日, 上午11:28
 */
package wangjg.codec.bitmap;

import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;

/**
 *
 * @author Jerry
 */
public class Bitmap {   
    byte[] bf;  //Bitmap File Head
    byte[] bi;  //Bitmap Info Head
    public boolean type;
    public int nsize;
    public int nwidth;
    public int nheight;
    int pixelbits;
    int imagesize;
    int hResolution;
    int vResolution;
    int colors;
    int importantcolors;
    
    int npad;
    
    byte[] bdata; //Image Data source
    int[] ndata; 
    
    int nNumColors;
    int[] npalette;
    byte[] bpalette;
    
    /** Creates a new instance of Bitmap */
    public Bitmap(File file){
    try{
        bf=new byte[14];
        bi=new byte[40];
        FileInputStream in=new FileInputStream(file);
        in.read(bf, 0, bf.length);//读入文件头
        in.read(bi, 0, bi.length);//读入信息头
        
        //处理文件头
        if(((char)(bf[0]&0xff)=='B')&&((char)(bf[1]&0xff)=='M')){
            type=true;
        }else{
            type=false;
            return;
        }
        nsize=(((int)bf[5]&0xff)<<24)
                |(((int)bf[4]&0xff)<<16)
                |(((int)bf[3]&0xff)<<8)
                |((int)bf[2]&0xff);
        //bf[6..9]=0 保留字
        //bf[10..13] 文件偏移量
        //文件头处理完毕
        
        //处理信息头
        //bi[0..3]信息头长度 默认为40
        //位运算计算宽度
        nwidth=(((int)bi[7]&0xff)<<24)
                    |(((int)bi[6]&0xff)<<16)
                    |(((int)bi[5]&0xff)<<8)
                    |((int)bi[4]&0xff);
        //位运算计算长度
        nheight=(((int)bi[11]&0xff)<<24)
                    |(((int)bi[10]&0xff)<<16)
                    |(((int)bi[9]&0xff)<<8)
                    |((int)bi[8]&0xff);
        //bi[12..13]=1 位面数
        //计算象素长度
        pixelbits=(((int)bi[15]&0xff)<<8)|((int)bi[14]&0xff);
        //bi[16..19]=0 不压缩
        //位图数据大小
        imagesize=(((int)bi[23]&0xff)<<24)
                    |(((int)bi[22]&0xff)<<16)
                    |(((int)bi[21]&0xff)<<8)
                    |((int)bi[20]&0xff);
        //水平和垂直分辨率
        hResolution=(((int)bi[27]&0xff)<<24)
                    |(((int)bi[26]&0xff)<<16)
                    |(((int)bi[25]&0xff)<<8)
                    |((int)bi[24]&0xff);
        vResolution=(((int)bi[31]&0xff)<<24)
                    |(((int)bi[30]&0xff)<<16)
                    |(((int)bi[29]&0xff)<<8)
                    |((int)bi[28]&0xff);
        //颜色数
        colors=(((int)bi[35]&0xff)<<24)
                    |(((int)bi[34]&0xff)<<16)
                    |(((int)bi[33]&0xff)<<8)
                    |((int)bi[32]&0xff);
        //指定重要颜色数
        importantcolors=(((int)bi[39]&0xff)<<24)
                    |(((int)bi[38]&0xff)<<16)
                    |(((int)bi[37]&0xff)<<8)
                    |((int)bi[36]&0xff);
        //信息头处理完毕
        
        if(pixelbits==24){
            npad=(imagesize/nheight)-nwidth*3;
            ndata=new int[nheight*nwidth];
            bdata=new byte[(nwidth+npad)*3*nheight];
            in.read(bdata, 0, (nwidth+npad)*3*nheight);
            int nindex=0;
            for(int j=0;j<nheight;j++){
                for(int i=0;i<nwidth;i++){
                       ndata[nwidth*(nheight-j-1)+i]=(255&0xff)<<24
                                                    |(((int)bdata[nindex+2]&0xff)<<16)
                                                    |(((int)bdata[nindex+1]&0xff)<<8)
                                                    |(int)bdata[nindex]&0xff;
                       nindex+=3;
                }
                nindex+=npad;
            }
        }else if(pixelbits==8){
            nNumColors=colors>0?colors:(1&0xff)<<pixelbits;
            if (imagesize == 0){
                imagesize = ((((nwidth*pixelbits)+31) & ~31 ) >> 3);
                pixelbits *= nheight;
            }
            npalette=new int[nNumColors];
            bpalette = new byte [nNumColors*4];
            in.read(bpalette,0,nNumColors*4);
            int nindex8 = 0;
            for (int n = 0; n < nNumColors; n++){
                npalette[n] = (255&0xff)<<24
                            |(((int)bpalette[nindex8+2]&0xff)<<16)
                            |(((int)bpalette[nindex8+1]&0xff)<<8)
                            |(int)bpalette[nindex8]&0xff;
                nindex8 += 4;
            }
            npad=(imagesize/nheight)-nwidth;
            ndata = new int[nwidth*nheight];
            bdata = new byte[(nwidth+npad)*nheight];
            in.read(bdata, 0, (nwidth+npad)*nheight);
            nindex8=0;
            for (int j = 0; j < nheight; j++){
                for (int i = 0; i < nwidth; i++){
                    ndata[nwidth*(nheight-j-1)+i]=npalette[((int)bdata[nindex8]&0xff)];
                    nindex8++;
                }
                nindex8 += npad;
            }
        }
    }
    catch(Exception e){
        System.out.println("File I/O error from Class Bitmap");
    }
    }
    
    public byte[] getbdata(){
        return bdata;
    } 
    
    public Image toImage(){
        if(pixelbits==24){
            Toolkit tk = Toolkit.getDefaultToolkit();
            Image img=tk.createImage(new MemoryImageSource(nwidth,nheight,ndata,0,nwidth));
            return img;
        }
        else if(pixelbits==8){
            Toolkit tk = Toolkit.getDefaultToolkit();
            Image img=tk.createImage(new MemoryImageSource(nwidth,nheight,ndata,0,nwidth));
            return img;
        }
        else return (Image)null;
    }
}
